import datetime
import backtrader as bt1
import calendar


def str2date(date_str, _format_str="%Y-%m-%d %H:%M:%S"):
    return datetime.datetime.strptime(date_str, _format_str)


def date2str(date, _format_str="%Y-%m-%d %H:%M:%S"):
    return date.strftime(_format_str)


def date2timestamp(date):
    return date.timestamp()


def recent_date(end_time, date="1month"):
    if date == "1month":
        new_date = end_time - datetime.timedelta(days=30)
        return new_date, f"{date}[{new_date.strftime('%Y%m%d')}]"
    elif date == "3month":
        new_date = end_time - datetime.timedelta(days=90)
        return new_date, f"{date}[{new_date.strftime('%Y%m%d')}]"
    elif date == "6month":
        new_date = end_time - datetime.timedelta(days=180)
        return new_date, f"{date}[{new_date.strftime('%Y%m%d')}]"
    elif date == "ytd":
        if isinstance(end_time, datetime.datetime):
            new_date = datetime.datetime(end_time.year, 1, 1)
        else:
            new_date = datetime.date(end_time.year, 1, 1)
        return new_date, f"{date}[{new_date.strftime('%Y%m%d')}]"
    else:
        return None, None


def str2timestamp(date, _format_str="%Y-%m-%d %H:%M:%S"):
    return date2timestamp(str2date(date, _format_str))


def timestamp2date(timestamp):
    return datetime.datetime.fromtimestamp(timestamp)


def timestamp2str(timestamp, _format_str="%Y-%m-%d %H:%M:%S"):
    return date2str(timestamp2date(timestamp), _format_str)

def parse_timeframe(timeframe="1h"):
    _timeframe = timeframe[-1].lower()
    _compression = int(timeframe[0:-1])

    timeframe, compression, total_minutes = None, None, None
    if _timeframe == 'h':
        timeframe = bt1.TimeFrame.Minutes
        compression = _compression * 60
        total_minutes = compression
    elif _timeframe == 'd':
        timeframe = bt1.TimeFrame.Days
        compression = _compression
        total_minutes = _compression * 24 * 60
    elif _timeframe == 'm':
        timeframe = bt1.TimeFrame.Minutes
        compression = _compression
        total_minutes = compression
    elif _timeframe == 'w':
        timeframe = bt1.TimeFrame.Weeks
        compression = _compression
        total_minutes = _compression * 7 * 24 * 60
    return timeframe, compression, total_minutes


def current_dt(dt, timeframe="d"):
    timeframe = timeframe.lower()
    if timeframe == "d":
        dtkey = datetime.datetime(dt.year, dt.month, dt.day)
    elif timeframe == "w":
        isoyear, isoweek, isoweekday = dt.isocalendar()
        sunday = dt + datetime.timedelta(days=7 - isoweekday)
        dtkey = datetime.datetime(sunday.year, sunday.month, sunday.day)
    elif timeframe == "m":
        _, lastday = calendar.monthrange(dt.year, dt.month)
        dtkey = datetime.datetime(dt.year, dt.month, lastday)
    elif timeframe == "y":
        dtkey = datetime.date(dt.year, 12, 31)
    else:
        dtkey = datetime.datetime(dt.year, dt.month, dt.day)
    return dtkey


def previous_dt(dt, timeframe="d"):
    timeframe = timeframe.lower()
    if timeframe == "d":
        dt -= datetime.timedelta(days=1)
        dtkey = datetime.datetime(dt.year, dt.month, dt.day)
    elif timeframe == "w":
        dt -= datetime.timedelta(days=7)
        isoyear, isoweek, isoweekday = dt.isocalendar()
        sunday = dt + datetime.timedelta(days=7 - isoweekday)
        dtkey = datetime.datetime(sunday.year, sunday.month, sunday.day)
    elif timeframe == "m":
        if dt.month == 1:
            _, lastday = calendar.monthrange(dt.year - 1, 12)
            dtkey = datetime.datetime(dt.year - 1, 12, lastday)
        else:
            _, lastday = calendar.monthrange(dt.year, dt.month - 1)
            dtkey = datetime.datetime(dt.year, dt.month - 1, lastday)
    elif timeframe == "y":
        dtkey = datetime.date(dt.year, 12, 31)
    else:
        dtkey = datetime.datetime(dt.year, dt.month, dt.day)
    return dtkey

def next_dt(dt, timeframe="d"):
    timeframe = timeframe.lower()
    if timeframe == "d":
        dtkey = dt + datetime.timedelta(days=1)
    elif timeframe == "w":
        dtkey = dt + datetime.timedelta(weeks=1)
    elif timeframe == "m":
        if dt.month < 12:
            _, lastday = calendar.monthrange(dt.year, dt.month + 1)
            dtkey = datetime.datetime(dt.year, dt.month + 1, lastday)
        else:
            _, lastday = calendar.monthrange(dt.year + 1, 1)
            dtkey = datetime.datetime(dt.year + 1, 1, lastday)

    elif timeframe == "y":
        dtkey = datetime.date(dt.year + 1, 12, 31)
    else:
        dtkey = dt + datetime.timedelta(days=1)
    return dtkey